package test.ui.img;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.DisplayMode;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.Image;

import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JRootPane;


import hyl.base.medium.MyUI;


/**
 * 
 * 这是一个仿canvasframe 的组件 用于理解 CanvasFrame,没有太大意义
 * 
 * 除非我们要开发java 或android 客户端
 * 
 * 相比于javacv 这个类不考虑伽马颜色偏差<br> 如果要减少色彩失真可以使用
 *  javacv的 CanvasFrame Java2DFrameConverter
 * 
 * @author 37798955@qq.com
 *
 */
public class CVFrame extends JFrame {

	JFrame frame;
	

	public CVFrame(String 标题, int 宽, int 高) {

		/*
		 * 使此窗口的大小适合其子组件的首选大小和布局。 如果任意一个维度小于前面调用setMinimumSize方法指定的最小大小，
		 * 则窗口的结果宽度和高度将自动放大。 如果窗口和/或其所有者还不可显示，则在计算首选大小之前， 将使它们都可显示。窗口在计算其大小后被验证。
		 */

	}

	Color 背景色;

	public void set背景色(Color color) {
		背景色 = color;
	}

	Canvas 画布;

	public void create画布() {
		画布 = new Canvas() {
			@Override
			public void update(Graphics g) {
				paint(g);
			}

			@Override
			public void paint(Graphics g) {
				// Calling BufferStrategy.show() here sometimes throws
				// NullPointerException or IllegalStateException,
				// but otherwise seems to work fine.
				try {
					if (画布.getWidth() <= 0 || 画布.getHeight() <= 0) {
						return;
					}
					BufferStrategy strategy = 画布.getBufferStrategy();
					do {
						do {
							g = strategy.getDrawGraphics();
							if (背景色 != null) {
								g.setColor(背景色);
								g.fillRect(0, 0, getWidth(), getHeight());
							}
							if (图像 != null) {
								g.drawImage(图像, 0, 0, getWidth(), getHeight(), null);
							}
							if (图像2 != null) {
								g.drawImage(图像2, 0, 0, getWidth(), getHeight(), null);
							}
							g.dispose();
						} while (strategy.contentsRestored());
						strategy.show();
					} while (strategy.contentsLost());
				} catch (NullPointerException e) {
				} catch (IllegalStateException e) {
				}
			}
		};
		if (是否全屏) {
			画布.setSize(getSize());

		} else {
			画布.setSize(10, 10); // mac bug

		}
		getContentPane().add(画布);
		画布.setVisible(true);
		画布.createBufferStrategy(2);
		// canvas.setIgnoreRepaint(true);
	}

	DisplayMode 显示模式;
	boolean 是否全屏;

//	double 屏幕伽马值 = 1.0;
//	double 图像伽马值 = 1.0;
	/**
	 * 先
	 * 
	 * @param fullScreen  是否全屏
	 * @param displayMode 像素深度和尺寸
	 * @param gamma       色彩伽马值
	 */
	void init(final boolean fullScreen, final DisplayMode displayMode) {
		是否全屏 = fullScreen;
		显示模式 = displayMode;

		Runnable r = new Runnable() {
			public void run() {

//			  KeyboardFocusManager.getCurrentKeyboardFocusManager().
//              addKeyEventDispatcher(keyEventDispatch);

				// 获取当前ui对象的图形配置驱动
				GraphicsDevice gd = getGraphicsConfiguration().getDevice();
				DisplayMode d = gd.getDisplayMode(), d2 = null;
				if (displayMode != null && d != null) {
					int w = displayMode.getWidth();
					int h = displayMode.getHeight();
					int b = displayMode.getBitDepth();
					int r = displayMode.getRefreshRate();
					d2 = new DisplayMode(w > 0 ? w : d.getWidth(), h > 0 ? h : d.getHeight(),
							b > 0 ? b : d.getBitDepth(), r > 0 ? r : d.getRefreshRate());
				}
				if (是否全屏) {
					setUndecorated(true);
					getRootPane().setWindowDecorationStyle(JRootPane.NONE);
					setResizable(false);
					gd.setFullScreenWindow(CVFrame.this);
				} else {
					setLocationByPlatform(true);
				}
				if (d2 != null && !d2.equals(d)) {
					gd.setDisplayMode(d2);
				}
//				double g = 屏幕伽马值 == 0.0 ? MyUI.get伽马(gd) : 屏幕伽马值;
//				图像伽马值 = g == 0.0 ? 1.0 : 1.0 / g;

				frame.setVisible(true);
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				create画布();
				// set画布尺寸(宽, 高);
				frame.pack();
			}
		};
		MyUI.do委托并等待(r);
	}

	Image 图像;

	public void show图像(Image img) {
		图像 = img;
		showImage(img);
	}

	BufferedImage 图像2;

	public void show图像(BufferedImage img) {
		图像2 = img;
		showImage(img);
	}

//	    public void showImage(Frame image, boolean flipChannels) {
//	        showImage(converter.getBufferedImage(image, converter.getBufferedImageType(image) ==
//	                BufferedImage.TYPE_CUSTOM ? 1.0 : inverseGamma, flipChannels, null));
//	    }
	boolean 是否需要重置窗体大小;
	double 图像缩放比例;

	void showImage(Image image) {
		if (image == null) {
			return;
		} else if (isResizable() && 是否需要重置窗体大小) {
			int w = (int) Math.round(image.getWidth(null) * 图像缩放比例);
			int h = (int) Math.round(image.getHeight(null) * 图像缩放比例);
			set画布尺寸(w, h);
		}

		图像 = image;
		画布.paint(null);
	}

//	    public Graphics2D createGraphics() {
//	        if (图像2 == null || 图像2.getWidth() != 画布.getWidth() || 图像2.getHeight() != 画布.getHeight()) {
//	            BufferedImage newbuffer = 画布.getGraphicsConfiguration().createCompatibleImage(
//	            		画布.getWidth(), 画布.getHeight(), Transparency.TRANSLUCENT);
//	            if (图像2 != null) {
//	                Graphics g = newbuffer.getGraphics();
//	                g.drawImage(图像2, 0, 0, null);
//	                g.dispose();
//	            }
//	            图像2 = newbuffer;
//	        }
//	        return 图像2.createGraphics();
//	    }
	public void do释放绘图组件(Graphics2D g) {
		g.dispose();
		画布.paint(null);
	}

	public void set画布尺寸(final int width, final int height) {
		Dimension d = 画布.getSize();
		if (d.width == width && d.height == height) {
			return;
		}

		Runnable r = new Runnable() {
			public void run() {
				// 显然在Linux的Java代码中有一个bug，解决方法:
				// 初次调整画布大小时,边界效果不好
				// 先顶开一个像素,再将画布调整到所需的大小。。。嘘！
				setExtendedState(NORMAL); // 当非最大化时
				画布.setSize(width, height);
				pack();
				画布.setSize(width + 1, height + 1);
				画布.setSize(width, height);
				是否需要重置窗体大小 = false;
			}
		};
		// invokeLater在把可运行的对象放入队列后就返回，而invokeAndWait一直等待知道已启动了可运行的run方法才返回。
		// EventQueue.invokeLater(runnable);
//通过事件队列 跳转窗体尺寸
		MyUI.do委托并等待(r);
	}

	public static void 鼠标事件(final CVFrame[] frames) {

		class MovedListener extends ComponentAdapter {
			boolean moved = false;

			@Override
			public void componentMoved(ComponentEvent e) {
				moved = true;
				Component c = e.getComponent();
				synchronized (c) {
					c.notify();
				}
			}
		}
		final MovedListener movedListener = new MovedListener();

		// 在平铺中为摄影机布置画布帧
		int canvasCols = (int) Math.round(Math.sqrt(frames.length));
		if (canvasCols * canvasCols < frames.length) {

			// 如果我们找不到一个正方形，就用水平布局
			// 因为屏幕通常比照相机宽。。。
			// 我们还有标题栏、任务栏、菜单等
			// 占用垂直空间
			canvasCols++;
		}
		int canvasX = 0, canvasY = 0;
		int canvasMaxY = 0;
		for (int i = 0; i < frames.length; i++) {
			final int n = i;
			final int x = canvasX;
			final int y = canvasY;
			try {
				movedListener.moved = false;
				EventQueue.invokeLater(new Runnable() {
					public void run() {
						frames[n].addComponentListener(movedListener);
						frames[n].setLocation(x, y);
					}
				});
				int count = 0;
				while (!movedListener.moved && count < 5) {
					// 等到窗口管理器真正放置我们的窗口。。。
					// 等待最多500毫秒，因为这不起作用，如果
					// 我们正在处理事件调度线程。还有一些窗户
					// 像Windows这样的管理者并不总是向我们发送事件。。。
					synchronized (frames[n]) {
						frames[n].wait(100);
					}
					count++;
				}
				EventQueue.invokeLater(new Runnable() {
					public void run() {
						frames[n].removeComponentListener(movedListener);
					}
				});
			} catch (java.lang.Exception ex) {
			}
			canvasX = frames[i].getX() + frames[i].getWidth();
			canvasMaxY = Math.max(canvasMaxY, frames[i].getY() + frames[i].getHeight());
			if ((i + 1) % canvasCols == 0) {
				canvasX = 0;
				canvasY = canvasMaxY;
			}
		}
	}
}
